home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / text / tex / texas.lha / texas.c < prev    next >
C/C++ Source or Header  |  1992-08-11  |  15KB  |  497 lines

  1. /*-----------------------------------------*\
  2. >  texas.c (c) 1992 by Jean-Pierre RIVIERE  <
  3. \*-----------------------------------------*/
  4.  
  5. /* necessite que parse.c ait ete compile
  6. *  avec ERR_MESS_WITHOUT_LETTER pas defini
  7. */
  8. #include <stdio.h>
  9. #include "parse.h"
  10.  
  11. #ifdef AMIGA
  12. #  define ERROR_CODE 5
  13. #else
  14. #  define ERROR_CODE 5
  15. #endif
  16.  
  17. #define OPTIONS "h t c;i;b s "
  18. #define OPTION_AIDE  0
  19. #define DEJATEX   1
  20. #define COLONNES  2
  21. #define INPUT     3
  22. #define BYE_END   4
  23. #define ESPACE    5
  24. #define COLDEF    72
  25. #define COLMIN    20
  26. #ifndef   ENGLISH
  27. #  define USAGE      "USAGE : texas [-h] [-t] [-c <colonnes>] [<entree> [<sortie>]]\n"
  28. #  define AVIS       "tExas (c) 1992 par Jean-Pierre RIVIERE\n"
  29. #  define REMARQUE   "%% --- traduction automatique ---\n"
  30. #  define FORMAT     "a4"
  31. #define AIDE   "tExas permet de traduire un texte à la norme Ansi en un" \
  32.    " source TeX, qui devra\ncependant être édité. Si vous avez un source" \
  33.    " TeX en 8 bits, l'option -t vous\npermettra de le transformer en 7" \
  34.    " bits.\nL'option -c permet de préciser la colonne de césure pour les" \
  35.    " textes d'entrée\nnon-TeX.\n" \
  36.    "L'option -i permet de préciser le texte à inclure au début et si un" \
  37.    "tiret est indiqué (\"-i -\"), de ne rien inclure du tout.\n" \
  38.    "L'option -b indique de ne pas ajouter \\bye en fin de texte.\n" \
  39.    "L'option -s enlève les espaces inutiles (très utile avec l'option -c).\n" \
  40.    "L'option -h sert a afficher ce texte d'aide."
  41. const char ERR_OUVERTURE [] = "impossible d'ouvrir %s\n";
  42. #else
  43. #  define USAGE      "USAGE : texas [-h] [-t] [-c <columns>] [<input> [<output>]]\n"
  44. #  define AVIS       "tExas (c) 1992 by Jean-Pierre RIVIERE\n"
  45. #  define REMARQUE   "%% --- automatic translation ---\n"
  46. #  define FORMAT     "a4"
  47. #define AIDE   "tExas allows that a text written according to the Ansi norm" \
  48.    " to be converted\ninto a TeX source which you should then edit. If you" \
  49.    " have an 8 bits TeX\nsource, the -t option will make the equivalent TeX" \
  50.    " 7 bits source out of it.\nThe caesura columnn can be precised with the" \
  51.    " -c option if the input text is\nnot already a TeX source.\n" \
  52.    "The -i option specifies with text to include at the beginning, and" \
  53.    " none if\nyou put a dash as the text name (\"-i -\").\n" \
  54.    "The -b option indicates to not add a \\bye at the end of the text.\n" \
  55.    "The -s option trashes extra-blanks (very useful with the -c option).\n" \
  56.    "The -h option brings you this help text."
  57. const char ERR_OUVERTURE [] = "cannot open %s\n";
  58. #endif
  59.  
  60. typedef struct {
  61.    char * commande;  /* commande ou macro TeX   */
  62.    char code [4]; /* code de la séquence escape */
  63. } sequence;
  64.  
  65. #ifdef DEBUG
  66.  
  67. void prseq (sequence * seq)
  68.    /* affiche l'adresse et le contenu d'une séquence   */
  69. {
  70.    printf("sequence : ");
  71.    if (!seq) {
  72.       printf("NULL\n");
  73.       return;
  74.    }
  75.    if (seq->code[0] == '\0')
  76.       printf("~Null\n");
  77.    printf("%x : %s --> %s .\n", seq, seq->code, seq->commande);
  78. }
  79.  
  80. #endif
  81.  
  82. extern char * ListeSpeciaux [];
  83. extern sequence ListeSequences [];
  84.  
  85. #define usage() { \
  86.    fprintf(stderr, USAGE); \
  87.    exit(ERROR_CODE);   \
  88.    }
  89.  
  90. #define traduire_special(c,sortie)  \
  91.    if (c >= 0xA0) \
  92.       fprintf((sortie), ListeSpeciaux[(c) - 0xA0]);   \
  93.    else  \
  94.       fputc(' ', sortie)
  95.  
  96. void traduire_sequence (FILE * entree, FILE * sortie)
  97.  
  98. {
  99.    sequence * seq;
  100.    short sep;
  101.    short suite;   /* utile en cas de séquences enchaînées */
  102.    char c [3];
  103.  
  104. #  ifndef ENGLISH
  105.    static const char * messErreur = " escape séquence a l'indice";
  106. #  define MAUVAISE   "mauvaise"
  107. #  define FAUSSE  "fausse"
  108. #  define INCONNUE   "inconnue"
  109. #  define NOCOLINTEX "pas de specification de colonnes autorisée en mode TeX\n"
  110. #  define COLERR  "Nombre de colonnes incorrect, valeur par défaut (%d) prise\n"
  111. #  else /* ENGLISH */
  112.    static const char * messErreur = " escape sequence at offset";
  113. #  define MAUVAISE   "bad"
  114. #  define FAUSSE  "false"
  115. #  define INCONNUE   "unknown"
  116. #  define NOCOLINTEX "no columns specification authorized in TeX mode\n"
  117. #  define COLERR  "incorrect columns number, default value(%d) taken\n"
  118.    static const char * messErreur = " escape sequence at offset";
  119. #  endif /* ENGLISH */
  120.    static unsigned short imbrication;  /* de sequences escapes */
  121.  
  122.    if (fgetc(entree) != '[') {
  123.       fprintf(stderr, MAUVAISE "%s%d\n",  messErreur, ftell(entree) - 1);
  124.       return;
  125.    }
  126.    suite = 0;
  127.    do {
  128.       if (!isdigit(c[0] = fgetc(entree))) {
  129.          fprintf(sortie, ":%c=" MAUVAISE "%s%d\n",  c[0], messErreur, ftell(entree) - 1);
  130.          fprintf(stderr, "pseudo%s%d\n",  messErreur, ftell(entree) - 1);
  131.          return;
  132.       }
  133.       if (isdigit(c[1] = fgetc(entree))) {
  134.          sep = fgetc(entree);
  135.          c[2] = '\0';
  136.       } else {
  137.          sep = c[1];
  138.          c[1] = '\0';
  139.       }
  140.       if (sep != ';' && sep != 'm') {
  141.          fprintf(stderr, FAUSSE "%s%d\n", messErreur, ftell(entree) - 1);
  142.          return;
  143.       }
  144.       /* gestion de la sequence de RAZ    */
  145.       seq = ListeSequences;
  146.       if (*c == '0') {
  147.          while (imbrication--)
  148.              fprintf(sortie, "}");
  149.          imbrication = suite = 0;
  150.       } else {
  151.          imbrication += 1 - suite;
  152.          while (*seq->code != '\0' && strcmp(c, seq->code))
  153.             seq++;
  154.          if (!seq)
  155.             fprintf(stderr, INCONNUE "%s%d\n", messErreur, ftell(entree) - 1);
  156.          else
  157.             fprintf(sortie, "%s", seq->commande + suite);
  158.          suite = 1;  /* pour sauter { au debut   */
  159.       }
  160.    }while (sep == ';');
  161. }
  162.  
  163. void traduire (FILE * entree, FILE * sortie, short maxcol, char dejatex,
  164.                char economie)
  165.    /*
  166.       dejatex : indique qu'on traite un fichier deja oriente TeX,
  167.                 et par consequent on ne traduira que les que
  168.                 les caracteres etendus
  169.       maxcol : colonne de début de césure possible. nul si pas de
  170.                césure automatique.
  171.       economie : vrai si les espaces inutiles au sens TeX sont à supprimer
  172.    */
  173. {
  174.    short col = 0; /* colonnes en cours */
  175.    unsigned char c;  /* caractère lu */
  176.  
  177.    c = '\n';
  178.    while (!feof(entree)) {
  179.       if (c >= 128)
  180.          traduire_special(c, sortie);
  181.       else
  182.          switch (c) {
  183.          default :
  184.             fputc(c, sortie);
  185.             col++;
  186.             break;
  187.          case '{' :
  188.          case '}' :
  189.             if (dejatex) {
  190.                fputc(c, sortie);
  191.                break;
  192.             }
  193.             /* la plupart du temps, \char`\{ est plus beau que \{ */
  194.             fprintf(sortie, "\\char`\\%c", c);
  195.             col += 8;
  196.             break;
  197.          case '<' :
  198.          case '>' :
  199.             if (dejatex)
  200.                putchar(c);
  201.             else {
  202.                printf("$%c$", c);
  203.                col += 3;
  204.             }
  205.             break;
  206.          case ' ' :
  207.          case '\t' :
  208.             if (dejatex) {
  209.                fputc(c, sortie);
  210.                break;
  211.             }
  212.             if (!maxcol || ++col <= maxcol)
  213.                fputc(' ', sortie);
  214.             else {
  215.                fputc('\n', sortie);
  216.                col = 0;
  217.             }
  218.             if (economie) {
  219.                while ((c = fgetc(entree)) == ' ' || c == '\t');
  220.                continue;
  221.             }
  222.             break;
  223.          case '\f' :
  224.             fprintf(sortie, "\n\\vfill\\eject\n\n");
  225.             col = 0;
  226.             break;
  227.          case 27 :
  228.             traduire_sequence(entree, sortie);
  229.             break;
  230.          case '#' :
  231.          case '$' :
  232.          case '%' :
  233.          case '&' :
  234.          case '\\' :
  235.          case '^' :
  236.          case '_' :
  237.             if (dejatex)
  238.                fputc(c, sortie);
  239.             else {
  240.                /* \char`\ est parfois obligatoire et toujours plus beau */
  241.                fprintf(sortie, "\\char`\\%c ", c);
  242.                col += 9;
  243.             }
  244.             break;
  245.          case '-' :
  246.             if (dejatex) {
  247.                fputc(c, sortie);
  248.                break;
  249.             }
  250.             if ((c = fgetc(entree)) != '\n') {
  251.                fputc('-', sortie);
  252.                col++;
  253.             } else {
  254.                col = 0;
  255.                while ((c = fgetc(entree)) == ' ' || c == '\t');
  256.                if (!isalpha(c) && c < 0xC0)
  257.                   fprintf(sortie, "-\n");
  258.                else
  259.                   fprintf(sortie, "\\-%%\n"); /* pour conserver le découpage   */
  260.             }
  261.             continue;
  262.          case '\n' :
  263.             if (dejatex) {
  264.                fputc(c, sortie);
  265.                break;
  266.             }
  267.             {
  268.                short sauts = 0;   /* nombre de sauts de lignes */
  269.  
  270.                while ((c = fgetc(entree)) == '\n')
  271.                   sauts++;
  272.                /* risque d'espaces inutiles en début de ligne */
  273.                if (economie && (c == ' ' || c == '\t'))
  274.                   while ((c = fgetc(entree)) == ' ' || c == '\t');
  275.                /* s'il y a beaucoup de lignes sautées, on génère un
  276.                   espace vertical supplémentaire */
  277.                switch(sauts) {
  278.                case 0 :
  279.                   if (!maxcol || ++col >= maxcol) {
  280.                      fputc('\n', sortie);
  281.                      col = 0;
  282.                      break;
  283.                   }
  284.                   fputc(' ', sortie);
  285.                   break;
  286.                case 1 :
  287.                   fputc('\n', sortie);
  288.                   fputc('\n', sortie);
  289.                   col = 0;
  290.                   break;
  291.                case 2 :
  292.                case 3 :
  293.                   fprintf(sortie, "\n\n\\smallskip\n\n");
  294.                   col = 0;
  295.                   break;
  296.                case 4 :
  297.                case 5 :
  298.                   fprintf(sortie, "\n\n\\midskip\n\n");
  299.                   col = 0;
  300.                   break;
  301.                default :
  302.                   fprintf(sortie, "\n\n\\bigskip\n\n");
  303.                   col = 0;
  304.                   break;
  305.                }
  306.             }
  307.             continue;
  308.          }
  309.       c = fgetc(entree);
  310.    }
  311. }
  312.  
  313. void main (int narg, char * parg [])
  314.  
  315. {
  316.    FILE * entree;
  317.    FILE * sortie;
  318.    struct rapport rapport;
  319.    short colonnes;
  320.    char nopt;
  321.    char dejatex;
  322.    char economie;
  323.  
  324.    fprintf(stderr, AVIS);
  325.    if ((nopt = parse(OPTIONS, narg, parg, &rapport)) < 0) {
  326.       if (rapport.erreur == OPT_UNKNOWN_OPTION) {
  327.          fprintf(stderr, USAGE);
  328.          exit (0);
  329.       }
  330.       fprintf(stderr, ParseErrMess, rapport.lettre);
  331.       fputc('\n', stderr);
  332.       exit(1);
  333.    }
  334.    if (rapport.options[OPTION_AIDE]) {
  335.       puts(AIDE);
  336.       exit(0);
  337.    }
  338.    entree =stdin;
  339.    sortie = stdout;
  340.    if (rapport.narg) {
  341.       /* attention, si le premier argument est "-", on ne fait rien */
  342.       if (rapport.parg[0][0] != '-' || rapport.parg[0][1] != '\0')
  343.          if (!(entree = (FILE *) fopen(rapport.parg[0], "r"))) {
  344.             fprintf(stderr, ERR_OUVERTURE, rapport.parg[0]);
  345.             parse_cleanup();
  346.             exit(1);
  347.          }
  348.       if (rapport.narg == 2)
  349.          if (!(sortie = (FILE *) fopen(rapport.parg[1], "w"))) {
  350.             fprintf(stderr, ERR_OUVERTURE, rapport.parg[1]);
  351.             parse_cleanup();
  352.             /* exit fermera tout seul le premier fichier ouvert */
  353.             exit(1);
  354.          }
  355.    }
  356.    dejatex = rapport.options[DEJATEX];
  357.    economie = rapport.options[ESPACE];
  358.    colonnes = 0;
  359.    if (rapport.options[COLONNES])
  360.       if (dejatex)
  361.          fprintf(stderr, NOCOLINTEX);
  362.       else
  363.          if ((colonnes = atoi(rapport.arguments[COLONNES])) <= COLMIN)
  364.             fprintf(stderr, COLERR, colonnes = COLDEF);
  365.    if (!rapport.options[INPUT])
  366.       fprintf(sortie, REMARQUE "\\input " FORMAT "\n\n");
  367.    else if (rapport.arguments[INPUT][0] == '-' && rapport.arguments[INPUT][1] == '\0')
  368.       fprintf(sortie, REMARQUE "\n");
  369.    else
  370.       fprintf(sortie, REMARQUE "\\input %s\n\n", rapport.arguments[INPUT]);
  371.    traduire(entree, sortie, colonnes, dejatex, economie);
  372.    if (!rapport.options[BYE_END])
  373.       fprintf(sortie, "\n\n\\bye\n");
  374.    /* pour la fermeture des fichiers, on fait confiance a exit() */
  375.    exit(0);
  376. }
  377.  
  378. /* liste des macros traductions */
  379.  
  380. char * ListeSpeciaux [] = {
  381.    /* 0xa0 */ " ",
  382.    /* ¡ */ "!`",
  383.    /* ¢ */ "\\cents",
  384.    /* £ */ "\\pounds ",
  385.    /* ¤ */ "\\star ",
  386.    /* ¥ */ "\\yens ",
  387.    /* ¦ */ "$\\mid$",
  388.    /* § */ "\\S ",
  389.    /* ¨ */ "\\\"\\ ",
  390.    /* © */ "\\copyright ",
  391.    /* ª */ "$^{\\underbar{^{a}}}$",
  392.    /* « */ "$\\ll$",
  393.    /* ¬ */ "\\neg ",
  394.    /* ­ */ "{\\bf -}",
  395.    /* ® */ "\\reserved",
  396.    /* ¯ */ "$^{-}$",
  397.    /* ° */ "$^{\\circ}$",
  398.    /* ± */ "$\\pm $",
  399.    /* ² */ "$^{2}$",
  400.    /* ³ */ "$^{3}$",
  401.    /* ´ */ "\\prime ",
  402.    /* µ */ "$\\mu $",
  403.    /* ¶ */ "$\\P $",
  404.    /* · */ "\\cdot ",
  405.    /* ¸ */ "\\c \\ ",
  406.    /* ¹ */ "$^{1}$",
  407.    /* º */ "$^{\\underbar{\\circ}}$",
  408.    /* » */ "$\\gg$",
  409.    /* ¼ */ "$^{1}/_{4}$",
  410.    /* ½ */ "$^{1}/_{2}$",
  411.    /* ¾ */ "$^{3}/_{4}$",
  412.    /* ¿ */ "?`",
  413.    /* À */ "\\`A",
  414.    /* Á */ "\\\'A",
  415.    /* Â */ "\\^A",
  416.    /* Ä */ "\\\"A",
  417.    /* Ã */ "\\~A",
  418.    /* Å */ "\\AA ",
  419.    /* Æ */ "\\AE ",
  420.    /* Ç */ "\\c C",
  421.    /* È */ "\\`E",
  422.    /* É */ "\\\'E",
  423.    /* Ê */ "\\^E",
  424.    /* Ë */ "\\\"E",
  425.    /* Ì */ "\\`\\I ",
  426.    /* Í */ "\\\'\\I ",
  427.    /* Î */ "\\^\\I ",
  428.    /* Ï */ "\\\"\\I ",
  429.    /* Ð */ "\\crossedD",
  430.    /* Ñ */ "\\~N",
  431.    /* Ò */ "\\`O",
  432.    /* Ó */ "\\\'O",
  433.    /* Ô */ "\\^O",
  434.    /* Õ */ "\\~O",
  435.    /* Ö */ "\\\"O",
  436.    /* × */ "$\\times $",
  437.    /* Ø */ "\\O ",
  438.    /* Ù */ "\\`U",
  439.    /* Ú */ "\\\'U",
  440.    /* Û */ "\\^U",
  441.    /* Ü */ "\\\"U",
  442.    /* Ý */ "\\\'Y",
  443.    /* Þ */ "$\\OEthp$",
  444.    /* ß */ "\\ss ",
  445.    /* à */ "\\`a",
  446.    /* á */ "\\\'a",
  447.    /* â */ "\\^a",
  448.    /* ä */ "\\\"a",
  449.    /* ã */ "\\~a",
  450.    /* å */ "\\aa ",
  451.    /* æ */ "\\ae ",
  452.    /* ç */ "\\c c",
  453.    /* è */ "\\`e",
  454.    /* é */ "\\\'e",
  455.    /* ê */ "\\^e",
  456.    /* ë */ "\\\"e",
  457.    /* ì */ "\\`\\i  ",
  458.    /* í */ "\\\'\\i ",
  459.    /* î */ "\\^\\i ",
  460.    /* ï */ "\\\"\\i ",
  461.    /* ð */ "\\OEthd",
  462.    /* ñ */ "\\~n",
  463.    /* ò */ "\\`o",
  464.    /* ó */ "\\\'o",
  465.    /* ô */ "\\^o",
  466.    /* õ */ "\\~o",
  467.    /* ö */ "\\\"o",
  468.    /* ÷ */ "$\\div $",
  469.    /* ø */ "\\o ",
  470.    /* ù */ "\\`u",
  471.    /* ú */ "\\\'u",
  472.    /* û */ "\\^u",
  473.    /* ü */ "\\\"u",
  474.    /* ý */ "\\\'y",
  475.    /* þ */ "\\OEthpp",
  476.    /* ÿ */ "\\\"y"
  477. };
  478.  
  479. /* traduction en deux parties des séquences escape */
  480.  
  481. sequence ListeSequences [] = {
  482.    { "{\\bf ", '1' },
  483.    { "{", "2\0\0\0" },
  484.    { "{", "20\0\0" },
  485.    { "{", "21\0\0" },
  486.    { "{", "22\0\0" },
  487.    { "{", "23\0\0" },
  488.    { "{\\it ", "3\0\0\0" },
  489.    { "{", "30\0\0" },
  490.    { "{", "31\0\0" },
  491.    { "{", "32\0\0" },
  492.    { "{", "33\0\0" },
  493.    { "\\underbar{", "4\0\0\0" },
  494.    { "{", "7\0\0\0" },
  495.    { NULL, 0,0,0,0 }
  496. };
  497.